﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GOFconsole
{
    public class Chapter19_Composite
    {
        public void CompositeTest()
        {           
            #region 模型
            Composite root = new Composite("root"); //生成树根ROOT，长出两片叶子A,B
            root.Add(new Leaf("Leaf A"));
            root.Add(new Leaf("Leaf B"));

            Composite comp = new Composite("Composite X");  //长出分枝X，上面有两片叶XA,XB
            comp.Add(new Leaf("Leaf XA"));
            comp.Add(new Leaf("Leaf XB"));
            root.Add(comp);

            Composite comp2 = new Composite("Composite XY");  //分枝X上长出分枝XY，上面有两片叶XYA,XYB
            comp2.Add(new Leaf("Leaf XYA"));
            comp2.Add(new Leaf("Leaf XYB"));
            comp.Add(comp2);

            Leaf lC = new Leaf("Leaf C");    //根部又长出两片叶子C和D，D被吹走了
            Leaf lD = new Leaf("Leaf D");
            root.Add(lC);
            root.Add(lD);
            root.Remove(lD);

            root.Display(1);
            #endregion

            //Demo(OA系统)
            ConcreteCompany rootCompany = new ConcreteCompany("北京总公司");
            rootCompany.Add(new HRDepartment("总公司人力资源部"));
            rootCompany.Add(new HRDepartment("总公司财务部"));

            ConcreteCompany cc = new ConcreteCompany("华东地区分公司");
            cc.Add(new HRDepartment("华东地区分公司人力资源部"));
            cc.Add(new HRDepartment("华东地区分公司财务部"));
            rootCompany.Add(cc);

            ConcreteCompany cc1 = new ConcreteCompany("上海分公司");
            cc1.Add(new HRDepartment("上海分公司人力资源部"));
            cc1.Add(new HRDepartment("上海分公司财务部"));
            cc.Add(cc1);

            Console.WriteLine("\n 结构图: ");
            rootCompany.Display(1);
            Console.WriteLine("\n 职责");
            rootCompany.LineOfDuty();

        }
    }

    #region 模型
    //Component类，为组合中的对象声明接口，声明一个接口用于访问和管理Component的子部件
    abstract class Component_C19
    {
        protected string name;
        public Component_C19(string name)
        {
            this.name = name;
        }

        public abstract void Add(Component_C19 c);  //通常用ADD和REMOVE来提供增删子节点的功能
        public abstract void Remove(Component_C19 c);
        public abstract void Display(int depth);
    }
    //Leaf在组合中表示叶节点对象，叶节点没有子节点
    class Leaf : Component_C19
    {
        public Leaf(string name) 
            : base(name) 
        { }

        public override void Add(Component_C19 c)           //叶节点没有增加或删除分枝或叶子的功能，但这样可以消除
        {
            Console.WriteLine("Cannot add to a leaf!");     //叶节点和分枝节点对象在抽象层次的区别，具备完全一致的接口
        }
        public override void Remove(Component_C19 c)
        {
            Console.WriteLine("Cannot remove from a leaf!");
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + name);
        }
    }
    //Composite定义了分枝节点的行为，用来储存子部件，在Composite接口中实现与子部件有关的操作
    class Composite : Component_C19
    {
        private List<Component_C19> children = new List<Component_C19>();//子对象集合用来存储下属的分枝和叶

        public Composite(string name)
            : base(name)
        { }

        public override void Add(Component_C19 c)
        {
            children.Add(c);
        }
        public override void Remove(Component_C19 c)
        {
            children.Remove(c);
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + name);//显示分枝节点名称，并对其下级进行遍历

            foreach (var child in children)
            {
                child.Display(depth+2);
            }
        }
    }
    #endregion
    
    #region Demo(OA系统)
    //公司类(抽象类或接口)
    abstract class Company
    {
        protected string name;
        public Company(string name)
        {
            this.name=name;
        }

        public abstract void Add(Company c);
        public abstract void Remove(Company c);
        public abstract void Display(int depth);
        public abstract void LineOfDuty();  //履行职责方法，不同的部门履行不同的职责
    }
    //具体公司类
    class ConcreteCompany : Company
    {
        private List<Company> children = new List<Company>();

        public ConcreteCompany(string name)
            : base(name)
        { }

        public override void Add(Company c)
        {
            children.Add(c);
        }
        public override void Remove(Company c)
        {
            children.Remove(c);
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + name);//显示分枝节点名称，并对其下级进行遍历

            foreach (var child in children)
            {
                child.Display(depth + 2);
            }
        }
        public override void LineOfDuty()   //履行职责
        {
            foreach (var child in children)
            {
                child.LineOfDuty();
            }
        }
    }

    //人力资源部
    class HRDepartment : Company
    {
        public HRDepartment(string name)
            : base(name)
        { }

        public override void Add(Company c)
        { }
        public override void Remove(Company c)
        { }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + name);
        }
        public override void LineOfDuty()
        {
            Console.WriteLine("{0} 员工招聘培训管理",name);
        }
    }

    //财务部
    class FinanceDepartment : Company
    {
        public FinanceDepartment(string name)
            : base(name)
        { }

        public override void Add(Company c)
        { }
        public override void Remove(Company c)
        { }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + name);
        }
        public override void LineOfDuty()
        {
            Console.WriteLine("{0} 公司财务收支管理", name);
        }
    }

    #endregion
}
